package es.uji.viselab.experiment;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import es.uji.viselab.benchmark.database.DatabaseCatalog;
import es.uji.viselab.benchmark.process.BenchmarkProcessorCatalog;
import es.uji.viselab.image.camera.CameraCatalog;
import es.uji.viselab.image.process.ImageProcessCatalog;
import es.uji.viselab.image.source.ImageCatalog;
import es.uji.viselab.math.Matrix4;
import es.uji.viselab.model.ModelCatalog;
import es.uji.viselab.robot.RobotCatalog;
import es.uji.viselab.visualservoing.VSCatalog;

public class ExperimentParameters implements Serializable {
	private static final long serialVersionUID = 271598782620057478L;
	protected RobotCatalog robotModel;
	protected CameraCatalog camParameters;
	protected ExperimentTypesCatalog experimentType;
	protected ExperimentCatalog experiment;
	protected DatabaseCatalog databaseType;
	protected ModelCatalog model;
	protected Matrix4 target;
	protected double[] targetMatrix4List;
	private ImageProcessCatalog imageProcessor;
	private ImageCatalog imageSource;
	private VSCatalog vsMethod;
	private DatabaseCatalog databaseCatalog;
	private BenchmarkProcessorCatalog benchmarkingProcessorCatalog;

	public RobotCatalog getRobotModel() {
		return robotModel;
	}

	public void setRobotModel(RobotCatalog robotModel) {
		this.robotModel = robotModel;
	}

	public CameraCatalog getCamParameters() {
		return camParameters;
	}

	public void setCamParameters(CameraCatalog camParameters) {
		this.camParameters = camParameters;
	}


	static public ExperimentParameters load(String file) {
		String filename = "parameters.txt";
		ExperimentParameters ep = null;
		// Create input streams.
		FileInputStream fis;
		try {
			fis = new FileInputStream(filename);
			ObjectInputStream ois = new ObjectInputStream(fis);
			XMLDecoder in = new XMLDecoder(ois);
			ep = (ExperimentParameters) in.readObject();
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (ep.targetMatrix4List != null)
			ep.copyPoseListToMatrix();
		return ep;
	}

	public void copyPoseMatrixToList() {

		targetMatrix4List = new double[16];
		targetMatrix4List = target.getList();
	}

	public void copyPoseListToMatrix() {
		target = new Matrix4(targetMatrix4List);
	}

	public double[] getTargetMatrix4List() {
		return targetMatrix4List;
	}

	public void setTargetMatrix4List(double[] targetMatrix4List) {
		this.targetMatrix4List = targetMatrix4List;
	}

	static public void save(ExperimentParameters ep, String file) {
		String filename = "parameters.txt";
		if (ep.target != null)
			ep.copyPoseMatrixToList();
		try {
			FileOutputStream fos = new FileOutputStream(filename);
			// ObjectOutputStream oos = new ObjectOutputStream(new
			// FileOutputStream(filename));
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			XMLEncoder out = new XMLEncoder(oos);
			out.writeObject(ep);
			out.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void setExperimentType(ExperimentTypesCatalog e) {
		this.experimentType = e;

	}

	public ExperimentTypesCatalog getExperimentType() {
		return this.experimentType;
	}

	public void setDatabaseType(DatabaseCatalog db) {
		this.databaseType = db;

	}

	public DatabaseCatalog getDatabaseType() {
		return this.databaseType;
	}

	public void setModel(ModelCatalog model) {
		this.model = model;

	}

	public ModelCatalog getModel() {
		return this.model;
	}

	public Matrix4 getTarget() {

		if (this.target == null) {
			Matrix4 t = Matrix4.getTranslation(1.1, 0.2, 0.3);
			// I am not worried about the orientation,
			// as far the z axis is going down
			Matrix4 ry = Matrix4.getIdentityM();
			ry.rotY(Math.PI);
			t.mul(ry);
			Matrix4 rz = Matrix4.getIdentityM();
			rz.rotZ(Math.PI/6);
			t.mul(rz);
			this.target = t;
		}
		return this.target;
	}

	public void setTarget(Matrix4 target) {
		// By now, I am capable to work with VS position, not orientation
		// TODO
		Matrix4 t = Matrix4.getTranslation(target.m03, target.m13, target.m23);
		// I am not worried about the orientation,
		// as far the z axis is going down
		Matrix4 r = Matrix4.getIdentityM();
		r.rotY(Math.PI);
		t.mul(r);
		this.target = t;

	}

	public void setImageSource(ImageCatalog imageSource) {
		this.imageSource = imageSource;

	}

	public void setImageProcessor(ImageProcessCatalog imageProcessor) {
		this.imageProcessor = imageProcessor;
	}

	public ImageCatalog getImageSource() {
		return this.imageSource;
	}

	public ImageProcessCatalog getImageProcessor() {
		return this.imageProcessor;
	}

	public void setVSMethod(VSCatalog vs) {
		this.vsMethod = vs;
	}

	public VSCatalog getVSMethod() {
		return this.vsMethod;
	}

	public void setExperiment(ExperimentCatalog e) {
		this.experiment = e;
	}
	
	public ExperimentCatalog getExperiment(){
		return this.experiment;
	}

	public void setDatabase(DatabaseCatalog dbc) {
     this.databaseCatalog=dbc;		
	}
	
	public DatabaseCatalog getDatabase(){
		return this.databaseCatalog;
	}

	public void setBenchmarkingProcessor(BenchmarkProcessorCatalog bpc) {
       this.benchmarkingProcessorCatalog = bpc;
	}
	
	public BenchmarkProcessorCatalog getBenchmarkingProcessor(){
		return this.benchmarkingProcessorCatalog;
	}
	
}
